﻿using System;
using CygiaLog.Module;
using DistributedVisionRunner.Interface;
using DistributedVisionRunner.Interface.Model;
using Prism.Commands;
using Prism.Events;
using Prism.Mvvm;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Windows.Input;
using DistributedVisionRunner.Interface.Client;

namespace InProcessTests.ViewModels
{
    public class TestViewModel : BindableBase
    {
        private readonly IEventAggregator _ea;
        private readonly IVisionClient _client;
        private readonly List<byte[]> _images;
        private readonly CountdownEvent _parallelRunCountDownEvent = new CountdownEvent(3);



        public ICommand RunOnceCommand { get; }
        public ICommand RunParallelCommand { get; }
        public ICommand GetBoundariesCommand { get; }

        public TestViewModel(IEventAggregator ea)
        {
            _ea = ea;

            _client = new InProcessVisionClient(ea, "FullTest");
            _client.BoundaryItemsChanged += OnBoundaryItemsChanged;

            RunOnceCommand = new DelegateCommand(RunOnce);
            RunParallelCommand = new DelegateCommand(RunParallel);
            GetBoundariesCommand = new DelegateCommand(GetBoundaries);

            var image1 = ImageHelper.ReadByteTiff("Sample Data/byte2_underExposed.tif");
            var image2 = ImageHelper.ReadByteTiff("Sample Data/byte2.tif");
            var image3 = ImageHelper.ReadByteTiff("Sample Data/byte2_overExposed.tif");
            _images = new List<byte[]> { image1.data, image2.data, image3.data };
        }

        private void GetBoundaries()
        {
            var boundaries = _client.GetBoundaryItems();
        }

        private void RunParallel()
        {
            Log("Starting parallel processing ...");
            var stopwatch = Stopwatch.StartNew();
            _parallelRunCountDownEvent.Reset();
            for (int i = 0; i < 3; i++)
            {
                var localIndex = i;
                new Thread(() =>
                {
                    RunOneImage(localIndex);
                    _parallelRunCountDownEvent.Signal();
                }).Start();
            }

            _parallelRunCountDownEvent.Wait();
            Log($"Parallel processing finished in {stopwatch.ElapsedMilliseconds} ms");
        }

        private void RunOnce()
        {
            RunOneImage(0);
        }

        private void RunOneImage(int imageIndex)
        {
            Log($"Running image index = {imageIndex}");
            var stopwatch = Stopwatch.StartNew();
            var result = _client.RequestProcess($"image{imageIndex}", "Normal", 1, _images[imageIndex], DateTime.Now);
            if (result.ResultType != ResultType.ERROR)
            {
                Log($"Process for image finished in {stopwatch.ElapsedMilliseconds}ms, average={result.RawResults.DoubleResults.First(r => r.Name == "Average").Value}");

            }
            else
            {
                Log($"Process for image errored in {stopwatch.ElapsedMilliseconds}ms");
            }

        }

        private void Log(string message)
        {
            _ea.GetEvent<LogEvent>().Publish(("General", new LogItem($"TestViewModel> {message}")));
        }

        private void OnBoundaryItemsChanged(Dictionary<OutputDataType, List<BoundaryItem>> itemsDictionary)
        {

        }
    }
}
